using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Xml;
using System.Net;
using System.Text;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using Rest.Http;

namespace Rest.Transport
{
    /// <summary>
    /// This class will represents a REST transport method
    /// </summary>
    /// <remarks>
    /// Content types/media types, see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
    /// 
    /// Multipart messages
    /// See: http://en.wikipedia.org/wiki/MIME
    /// See: http://en.wikipedia.org/wiki/Content-type#Multipart_Messages
    /// 
    /// Supporting multipart messages requires some slight differences when 
    /// building request bodies.
    /// </remarks>
    public abstract class RestTransport
    {
        #region Properties
        private HttpContentType httpContentType = new FormUrlEncoded();
        private Boolean supportsBody = true;

        /// <summary>
        /// The HTTP method, defaults to GET
        /// </summary>
        private String httpMethod = "GET";

        /// <summary>
        /// HTTP Get transport
        /// </summary>
        public static GetRestTransport Get
        {
            get { return new GetRestTransport(); }
        }

        /// <summary>
        /// HTTP Post transport
        /// </summary>
        public static PostRestTransport Post 
        {
            get { return new PostRestTransport(); }
        }

        /// <summary>
        /// The content type encoding to use to format requests,
        /// defaults to URL encoding (application/x-www-form-urlencoded)
        /// </summary>
        /// <remarks> See: </remarks>
        public HttpContentType HttpContentType
        {
            get { return httpContentType; }
            set { httpContentType = value; }
        }

        /// <summary>
        /// The HTTP method associated with the current instance.
        /// Example: HEAD, GET, POST
        /// TODO: Consider renaming, perhaps "verb" makes more sense.
        /// </summary>
        public String HttpMethod
        {
            get { return httpMethod; }
            set { httpMethod = value; }
        }

        /// <summary>
        /// Value indicating the current transport supports a message body.
        /// The GET HTTP method for example, does not support a body.
        /// </summary>
        public Boolean SupportsBody
        {
            get { return supportsBody; }
            set { supportsBody = value; }
        }
        #endregion

        /// <summary>
        /// Creates an HttpWebRequest for the supplied URI, 
        /// parameters and data
        /// </summary>
        /// <param name="serviceUri"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public HttpWebRequest CreateRequest(Uri serviceUri,
            RestParameterCollection parameters) 
        {
            return CreateRequestCore(serviceUri, parameters);
        }

        /// <summary>
        /// Creates an HttpWebRequest for the supplied URI, 
        /// parameters and data
        /// </summary>
        /// <param name="serviceUri"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        protected virtual HttpWebRequest CreateRequestCore(Uri serviceUri,
            RestParameterCollection parameters)
        {
            return (HttpWebRequest)HttpWebRequest.Create(serviceUri);
        }

        /// <summary>
        /// Write the body of request to the supplied stream. Implementations
        /// should leave the stream open.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="parameters"></param>
        /// <param name="data"></param>
        /// <param name="characterEncoding"></param>
        public void WriteRequestBody(Stream stream, 
            RestParameterCollection parameters,
            RestDataItemCollection data, Encoding characterEncoding)
        {
            HttpContentType.WriteRequestBody(stream, parameters, data,
                characterEncoding);
        }
    }
}
